<template>
  <!-- 使用行布局容器 -->
  <div class="page-container">
    <!-- 左侧侧边栏 -->
    <SideMenu />
    
    <!-- 历史消息栏 (默认宽度为0) -->
    <div class="history-panel" :class="{ 'active': showHistory }">
      <div class="history-header">
        <h3>历史对话</h3>
        <button @click="closeHistory" class="close-btn">×</button>
      </div>
      <div class="history-content">
        <div v-if="loadingHistory" class="loading-history">加载中...</div>
        <div v-else-if="todayHistory.length === 0 && weeklyHistory.length === 0 && olderHistory.length === 0" class="empty-history">暂无历史对话</div>
        
        <!-- 今天的对话 -->
        <div class="history-section">
          <div class="history-section-title">今天</div>
          <div v-if="todayHistory.length === 0" class="empty-section">
            暂无今天的对话
          </div>
          <div v-for="(item, index) in todayHistory" :key="'today-'+index" class="history-item" @click="selectHistoryItem(item)">
            <div class="history-item-title">{{ item.content || '无标题对话' }}</div>
            <div class="history-item-time">{{ formatTime(item.createTime) }}</div>
          </div>
        </div>
        
        <!-- 本周的对话 -->
        <div class="history-section">
          <div class="history-section-title">本周</div>
          <div v-if="weeklyHistory.length === 0" class="empty-section">
            暂无本周的对话
          </div>
          <div v-for="(item, index) in weeklyHistory" :key="'week-'+index" class="history-item" @click="selectHistoryItem(item)">
            <div class="history-item-title">{{ item.content || '无标题对话' }}</div>
            <div class="history-item-time">{{ formatTime(item.createTime) }}</div>
          </div>
        </div>
        
        <!-- 更早的对话 -->
        <div class="history-section">
          <div class="history-section-title">更早</div>
          <div v-if="olderHistory.length === 0" class="empty-section">
            暂无更早的对话
          </div>
          <div v-for="(item, index) in olderHistory" :key="'older-'+index" class="history-item" @click="selectHistoryItem(item)">
            <div class="history-item-title">{{ item.content || '无标题对话' }}</div>
            <div class="history-item-time">{{ formatTime(item.createTime) }}</div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 聊天内容区域 (弹性填充剩余空间) -->
    <div class="main-content">
      <div class="header-bar">
        <div class="topic-header">
          <div class="title-row">
            <h1 class="topic-title">{{ getPageTitle() }}</h1>
          </div>
        </div>
      </div>
      <div class="chat-container" ref="chatContainer" @scroll="onScroll" @click="handlePageClick">
        <div class="messages-wrapper">
          <div class="message system" v-if="showWelcome">
            <div class="message-header">
              <img src="@/assets/icon/qipu-avatar.png" class="avatar" />
            </div>
            <div class="message-content">
              <div class="text">
                Hi, 我是小禾, 很高兴遇见你! 有需要随时召唤我 (^_^)，请输入或选择感兴趣的话题吧~
              </div>
              <div class="topic-list">
                <div
                  v-for="(item, index) in currentPageTopics"
                  :key="index"
                  class="topic-item"
                  :title = "item.primary?.summary"
                  @click="handleTopicItemClick(item)"
                >
                  {{ item.primary?.title + "   >"|| '加载中...' }}
                </div>
              </div>
            </div>
          </div>
          <template v-for="(message, index) in messages?.records" :key="index">
            <div :id="`message-${index}`" class="message-wrapper">
              <div class="message user" @click.stop="(e) => handleMessageClick(message, index, e)">
                <div v-if="messages?.p2m===false" class="message-content">
                  <div class="text">{{ message.askRecord?.content }}</div>
                </div>
              </div>
              <div class="message system">
                <div class="message-header">
                  <img :src="getAvatarSrc(message)" class="avatar" />
                </div>
                <div class="message-content">
                  <div class="text">
                    <markdown-renderer v-if="message.answerRecord?.content" :content="message.answerRecord?.content" />
                    <div v-if="!isPhaseEnd && index === (messages?.records?.length || 0) - 1" class="stop-output-btn">
                      <button @click="handleStopAll" title="停止输出">
                        <img src="@/assets/icon/stop.png" alt="停止输出" />
                      </button>
                    </div>
                    <!-- 添加消息操作按钮 -->
                    <div v-if="isMessageEnd(message)" class="message-actions">
                      <button @click="handleCopy(message.answerRecord?.content)" title="复制">
                        <img src="@/assets/icon/copy.png" alt="复制" />
                      </button>
                      <button @click="handleThumbUp(message)" :class="{ active: message.thumbup }" title="点赞">
                        <img :src="getThumbUpIcon(message)" alt="点赞" />
                      </button>
                      <button @click="handleThumbDown(message)" :class="{ active: message.thumbdown }" title="踩">
                        <img :src="getThumbDownIcon(message)" alt="踩" />
                      </button>
                      <button @click="handleRegenerate(message)" title="重新生成">
                        <img src="@/assets/icon/again.png" alt="重新生成" />
                      </button>
                    </div>
                  </div>
                  <!-- 添加relative信息列表 -->
                  <div v-if="getRelatives && getRelatives.length > 0 && index === (messages?.records?.length || 0) - 1 && isMessageEnd(message)" class="relatives-list">
                    <div class="relatives-title">相关话题：</div>
                    <div v-for="(item, idx) in getRelatives" :key="idx" class="relative-item" @click="handleRelativeItemClick(item)">
                      {{ item.title }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </template>
        </div>
      </div>
      <div class="input-container">
        <div class="input-wrapper">
          <unified-input-bar
            :isBlocking="isBlocking"
            :isVoiceMode="showVoiceInput"
            :showUpload="false"
            :artifacts="virtualArtifacts"
            :selectedArtifact="selectedArtifact"
            :showRagMode="true"
            :showHistory="true"
            @send="handleSend"
            @file-change="handleFileChange"
            @voice-result="handleVoiceResult"
            @toggle-mode="showVoiceInput = !showVoiceInput"
            @stop-all="handleStopAll"
            @select-artifact="handleSelectArtifact"
            @select-rag-mode="handleSelectRagMode"
            @history-click="handleHistoryClick"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, watch, nextTick } from 'vue';
import { DeleteKnotReaction, DecodeExchange, DeleteKnot,GetRecommendTopic } from '@/api/knot';
import { RegenKnotChat,CreateKnot, GeteKnot, CreateKnotChat, UpsertKnotReaction } from '@/api/knot';
import {ListKnots, ListExchangeRecord} from '@/api/knot'
import {ListTopics} from '@/api/subject'
import { Knot,DeleteKnotRequest, ListKnotExchangesRequest, ListKnotsRequest, RegenKnotRequest } from '@/types/proto/api/v1/knot_service';
import { CreateKnotRequest, GetKnotRequest,GetKnotRecommendTopicsResponse,CreateKnotChatRequest} from '@/types/proto/api/v1/knot_service';

import { Chat, Phase, Exchange, ExchageDirect,RecordUnit, UserRecordUnit } from '@/types/proto/api/v1/exchange_service';
import { TopicDef,Visibility } from '@/types/proto/common/common';
import SideMenu from '@/components/SideMenu.vue'
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'

import { getWssUrl } from '@/config';
import { InteractType, RagMode, ReactionType } from '@/types/proto/common/common';
import UnifiedInputBar from '@/components/UnifiedInputBar.vue';
import ShareOptions from './share_options.vue';
import EditDialog from '@/components/EditDialog.vue';
import { useRouter,useRoute } from 'vue-router'
import { WebSocketClient} from "@/utils/websocket";
import { ExchangeReocrdUnit, P2MExchangeRecord, P2MExchangeReocrdUnit } from '@/types/proto/api/v1/exchange_service';
import { useUserStore } from '@/store/user'
import { ElMessage } from 'element-plus'
import {GetSubjectRequest, ListTopicsResponse,GetTopicRequest, Subject} from '@/types/proto/api/v1/subject_service'
import qipuIcon from '@/assets/icon/qipu-avatar.png'
import { User } from '@/types/proto/api/v1/user_service'
import { ListUsers } from '@/api/user'
import {isToday, isThisWeek, formatTime} from '@/utils/time_utils'
import {Resource} from '@/types/proto/api/v1/resource_service'

const showVoiceInput = ref(true)
const router = useRouter()
const route = useRoute()
const showUpload = ref(false)

const isBlocking = ref(false);  // 添加状态控制是否在阻塞中
const isPhaseEnd = ref(true)
const currentAskId=ref('');
const ragMode=ref ('')
const currentKnotId = ref('');
const rootKnot = ref<Knot|null>(null)
const subject = ref<Subject | null>(null);
const topic =  ref<TopicDef | null>(null);
const wsSocket  = ref<WebSocketClient|null>(null);
const isFavor = ref(false)
const userStore = useUserStore()
import { GetSubject, GetTopic } from '@/api/subject'
import thumbupActive from '@/assets/icon/thumbup-active.png'
import thumbup from '@/assets/icon/thumbup.png'
import thumbdownActive from '@/assets/icon/thumbdown-active.png'
import thumbdown from '@/assets/icon/thumbdown.png'
const todayHistory = ref<Knot[]>([])
const weeklyHistory = ref<Knot[]>([])
const olderHistory = ref<Knot[]>([])
const topicsTotal = ref(0)
const topics = ref<TopicDef[]>([])
const knotFiles = ref<Resource[]|null>(null)
const currentPageTopics = computed(() => {
  return topics.value
})

const showWelcome = computed(() => {
  if (topic.value == null && rootKnot.value == null ) {
    return true
  }
  return false
})

interface RelativeInfo {
  title: string;
  summary: string;
}

const relatives = ref<RelativeInfo[]>([])
const isFetchingRelatives = ref(false)
const lastFetchedKnotUrn = ref('')
const fetchTimeout = ref<number | null>(null)

const fetchRelatives = async (knotUrn: string) => {
  // 如果正在获取或者已经获取过这个knot的相关话题，则跳过
  if (isFetchingRelatives.value || lastFetchedKnotUrn.value === knotUrn) {
    return
  }

  // 清除之前的延时
  if (fetchTimeout.value) {
    clearTimeout(fetchTimeout.value)
  }

  // 设置新的延时
  fetchTimeout.value = window.setTimeout(async () => {
    try {
      isFetchingRelatives.value = true
      
      const req = {urn: knotUrn}
      const res = await GetRecommendTopic(req)
      if (res && res.topics && res.topics.length > 0) {
        relatives.value = res.topics.map(t => ({title: t} as RelativeInfo))
        lastFetchedKnotUrn.value = knotUrn
        console.info("relatives:",  relatives.value )
      } else {
        relatives.value = []
      }
    } catch (error) {
      console.error('Failed to fetch recommend topics:', error)
      relatives.value = []
    } finally {
      isFetchingRelatives.value = false
      fetchTimeout.value = null
    }
  }, 1000) // 1秒延时
}

// 修改原来的 relvatives computed 属性
const getRelatives = computed(() => {
  if (rootKnot.value != null) {
    if (messages.value == null) {
      return null
    }
    let lastMessage = messages.value.records[messages.value.records.length - 1]
    if (lastMessage.phase != Phase.End) {
      return null
    }
    let knotUrn = lastMessage.answerId
    
    if (knotUrn.length < 1) {
      return null
    }

    console.log("get topic for ", knotUrn)
    // 当条件满足时，触发获取相关话题
    fetchRelatives(knotUrn)
    console.log("knot recommend topic ", relatives.value)
    return relatives.value
  } else if(topic.value != null) {
    console.log("fetch default topic ")
    relatives.value = []
    topic.value.units.forEach((t) =>{
      let r={title:t.title, summary:t.summary} as RelativeInfo
      relatives.value.push(r)
    })

    console.log("knot default topic ", relatives.value)
    return relatives.value 
  } else {
    return null
  }
})

defineOptions({
  name: 'TopicView',
  components: {
    'unified-input-bar': UnifiedInputBar
  }
})

const messages = ref<P2MExchangeRecord|null>(null);
const responders = ref<User[]>([])
const currentShareContent = ref({});
const handlePageClick = () => {
  if (messages.value) {
    messages.value.records = messages.value.records.map(msg => ({ ...msg, isSelected: false }));
  }
};

const endOutput = () => {
  console.log('endOutput called');
  sendMessageViaWebSocket("", Phase.End, currentAskId.value)
}

const clearBlocking = () => {
  isBlocking.value = false;
};

const handleStopAll = () => {
  console.error('handleStopAll is called');

  if (isPhaseEnd.value===false) {
    console.info("send end cmd, phae value:", isPhaseEnd.value)
    endOutput()
  }

  console.log("record info:", messages.value)
  if (messages.value) {
    console.log("record info record:", messages.value.records)
    let lastMessage = messages.value.records[messages.value.records.length - 1]
    if (lastMessage.phase === Phase.Prepare || lastMessage.phase === Phase.Begin) {
      if (lastMessage.answerRecord) {
        lastMessage.answerRecord.content = ''
      }
    }
    lastMessage.phase = Phase.End
  }

  isPhaseEnd.value=true
  clearBlocking();
};

const handleSound = async (content: string|undefined, messageIndex: number) => {
  
};

const handleVoiceResult = (ask: string) => {
  console.info('voice input:', ask);
  handleSend(ask)
}

const onSayMessage = (message: any) => {
  if (! messages.value) {
      return
  }
  if (messages.value.records.length === 0) return;
  const res = DecodeExchange(message);
  let isAppend = true
  if (isPhaseEnd.value === true) {
    return
  }

  console.log("onSayMessage res:", {content:res.content, answerId:res.answerId, askid:res.askId, phase:res.phase})
  switch (res.phase) {
      case Phase.Close:
          isPhaseEnd.value = true
          console.log('WebSocket message received phase close');
          wsSocket.value?.close();
          wsSocket.value = null;
          scrollToBottom();
          break;
      case Phase.Begin:
          updateLastMessage(res.content, true, false);
          break
      case Phase.End:
          isPhaseEnd.value = true
          console.log('WebSocket message received phase end:',res.answerId);
          messages.value.records[messages.value.records.length - 1].answerId = res.answerId;
          updateLastMessage(res.content, true, true);
          isBlocking.value = false; 
          console.error('set isBlocking to false');
          break;
      case Phase.Continue:
          isPhaseEnd.value = false
          if (messages.value.records[messages.value.records.length - 1].phase === Phase.Begin) {
              isAppend = false
          }
          updateLastMessage(res.content, isAppend);
          break;
      default:
          let lastMessage = messages.value.records[messages.value.records.length - 1];
          if (isPhaseEnd.value && lastMessage.askRecord?.content !== '...') {
              let askunit = {
                  content: lastMessage.askRecord?.content,
              } as RecordUnit

              let exRecord = {
                  askRecord: askunit,
                  answerRecord: {}
              } as P2MExchangeReocrdUnit;

              console.log("push exRecord 2:", exRecord)
              
              messages.value.records.push(exRecord);
              lastMessage = messages.value.records[messages.value.records.length - 1];
          }

          lastMessage.askId = res.askId
          lastMessage.answerId = res.answerId
          isPhaseEnd.value = false
          console.log('WebSocket message received phase:', res.phase);
          updateLastMessage(res.content);
          break;
  }
  messages.value.records[messages.value.records.length - 1].phase = res.phase    
  scrollToBottom();
}

const getPageTitle = () => {
  if (rootKnot.value != null) {
      return rootKnot.value.subject
  }

  let title = ''
  if (topic.value != null) {
    title += topic.value.primary?.title
  }

  if (subject.value!=null) {
    if (title.length >0) {
      let t = title.toUpperCase();
      let m = subject.value.matter.toUpperCase()
      if (t.includes(m)) {
        return title
      }
      title = subject.value.matter + ":" + title
    }
  }

  return title
}

const handleSend = async (message: string, regenerate: boolean = false, askId:string="") => {
  console.log("send msg:", message)
  if (isBlocking.value) {
    console.error('isBlocking is true, return');
    return;
  }

  if (! messages.value) {
    let record = {p2m:false} as P2MExchangeRecord;
    record.records=[]
    messages.value = record;
  }
  if (! regenerate) {
    let askunit = {
      content: message,
      createTime: new Date(),
    } as RecordUnit

    if (knotFiles.value != null) {
      askunit.resources = knotFiles.value
    }

    let exRecord = {
        askRecord: askunit,
        answerRecord: {}
    } as P2MExchangeReocrdUnit;
    
    messages.value.records.push(exRecord);
    console.log("push exRecord:", exRecord)
  }

  if (currentArtifact.value !== selectedArtifact.value) {
    currentArtifact.value = selectedArtifact.value;
    if (wsSocket.value && wsSocket.value.status() === WebSocket.OPEN) {
      wsSocket.value.close();
      wsSocket.value = null;
    }
  }
  
  await nextTick();
  scrollToBottom();
  isBlocking.value = true; 
  console.log('set isBlocking to true');
  relatives.value = []
  if (wsSocket.value && wsSocket.value.status() === WebSocket.OPEN) {
    if (isPhaseEnd.value) {
      sendMessageViaWebSocket(message, Phase.HELLO, askId);
    } else {
      sendMessageViaWebSocket(message);
    }
  } else {
    wsSocket.value = null;
    try {
      if (regenerate && askId != "") {
        regenKnot(askId)
      } else if (rootKnot.value == null) {
        createKnot(message);
      } else {
        createKnotChat(message);
      }
    } catch (error) {
      console.error('Failed to create knot:', error);
      updateLastMessage('抱歉，发生了一些错误。请稍后再试。');
    }
  }
  isPhaseEnd.value = false;
};

const handleFileChange = (files:Resource[]) =>{
  knotFiles.value = files
  console.log("file change:", knotFiles.value)
}

const updateLastMessage = (content: string, isAppend: boolean = false, isCompleted: boolean = false) => {
  if (! messages.value) {
      return
  }

  if (messages.value.records.length === 0) return;
 

  let record = messages.value.records[messages.value.records.length - 1].answerRecord
  if (! record) {
      record = {} as RecordUnit
      messages.value.records[messages.value.records.length - 1].answerRecord = record
  }
  // 更新消息显示
  if (isAppend) {
     record.content += content;
  } else {
      record.content  = content;
  }

  if (isCompleted) {
    messages.value.records[messages.value.records.length - 1].phase = Phase.End;
  }

  messages.value.records[messages.value.records.length - 1].answerRecord = record

  nextTick(() => {
    scrollToBottom();
  });
};

const createKnotChat = async (message: string) => {
  let chat = {
      content: message,
      interactType: InteractType.CHAT,
    } as CreateKnotRequest;

  if (knotFiles.value != null) {
    chat.resources = knotFiles.value
  }

  if (selectedArtifact.value) {
    chat.responders = [selectedArtifact.value];
  }

  const request = {
    urn: rootKnot.value?.urn,
    chat: chat,
  } as CreateKnotChatRequest;

  console.log('prepare to Knot created:');
  const response = await CreateKnotChat(request);
  console.log('Knot chat created:', response);
  if (rootKnot.value != null) {
    createWebSocketConnection(rootKnot.value.uid, response.urn);
  }
}

const handleShare = (message: P2MExchangeReocrdUnit, index: number) => {
  console.log("share click2");
  messages.value?.records.forEach((msg, i) => {
  if (i !== index) {
      msg.share = false;
    }
  });

  message.share = ! message.share;
  if (message.share) {
    let shareContent={"askId": message.askId, "subject":subject.value,"subject_urn":subject.value?.urn, "answerId":message.answerId, "user":message.askRecord?.content, "qipu":message.answerRecord?.content};
    currentShareContent.value = shareContent;
  }    
}

const createKnot = async (message: string) => {
  const request = {
    content: message,
    subject:subject.value?.matter,
    subjectUrn:subject.value?.urn,
    topicUrn:topic.value?.primary?.urn,
    interactType: InteractType.CHAT,
    visibility: Visibility.TENANT,
  } as CreateKnotRequest;

  if (knotFiles.value != null) {
    request.resources = knotFiles.value
  }

  if (selectedArtifact.value) {
    request.responders = [selectedArtifact.value];
  }

  console.log('prepare to Knot created:');
  CreateKnot(request).then((res:Knot) => {
      rootKnot.value = res
      createWebSocketConnection(res.uid, res.urn);
  })

}

const regenKnot = async (askId :string) => {
  let req = {urn:askId, dropChild:true} as RegenKnotRequest
  let res = await RegenKnotChat(req)
  if (rootKnot.value !=null && rootKnot.value.urn == askId) {
    rootKnot.value = res
  }

  if (rootKnot.value != null) {
    createWebSocketConnection(rootKnot.value.uid, res.urn);
  }
}

const handleThumbDown = async (message: P2MExchangeReocrdUnit) => {
  if (!message.answerId?.trim()) {
    console.warn('No knotId found for message');
    return;
  }
  if (message.thumbdown) {
    DeleteReaction(message.answerId, ReactionType.THUMBS_DOWN)
  } else {
    if (message.thumbup) {
      DeleteReaction(message.answerId, ReactionType.THUMBS_UP)
    }
    UpsertReaction(message.answerId, ReactionType.THUMBS_DOWN)  
    message.thumbdown = true
  }   
};

const handleThumbUp = async (message: P2MExchangeReocrdUnit) => {
  if (!message.answerId?.trim()) {
    console.warn('No knotId found for message');
    return;
  }

  if (message.thumbup) {
    console.log('delete thumbs up reaction');
    message.thumbup = false
    if (message.answerId.length > 0) {
      DeleteReaction(message.answerId, ReactionType.THUMBS_UP)
    }
  } else {
    if (message.thumbdown) {
      message.thumbdown = false
      if (message.answerId.length > 0) {
        DeleteReaction(message.answerId, ReactionType.THUMBS_DOWN)
      }
      
    }
    message.thumbup = true
    console.log('upsert thumbs up reaction');
    if (message.answerId.length > 0) {
      UpsertReaction(message.answerId, ReactionType.THUMBS_UP)  
    }
  }
};

const UpsertReaction = async (answerId: string, reactionType:ReactionType)  => {
  try {
    const response = await UpsertKnotReaction({knot: answerId, reactionType: reactionType});
    if (! messages.value) {
      return
    }

    if (messages.value.records.length < 1) {
      return
    }
    // 更新本地消息的点赞状态
    const messageIndex = messages.value.records.findIndex(msg => msg.answerId === answerId);
    if (messageIndex > -1) {
      let record = messages.value.records[messageIndex];
      if (!record) {
        return
      }
      switch (reactionType) {
        case ReactionType.THUMBS_UP:
          record.thumbup = true;
          break;
        case ReactionType.THUMBS_DOWN:
        record.thumbdown = true;
          break;
      }
      messages.value.records[messageIndex] = record;
    }
  } catch (error) {
    console.error('Failed to update reaction:', error);
    let title = ""
    switch (reactionType) {
      case ReactionType.THUMBS_UP:
        title="点赞失败";
        break;
      case ReactionType.THUMBS_DOWN:
        title="狂踩失败";
        break;
    }
  }
};

const DeleteReaction = async (answerId: string, reactionType:ReactionType)  => {
  try {
    const response = await DeleteKnotReaction({knot: answerId, reactionType: reactionType, urn:""});
    if (! messages.value) {
      return
    }

    if (messages.value.records.length < 1) {
      return
    }
    // 更新本地消息的点赞状态
    const messageIndex = messages.value.records.findIndex(msg => msg.answerId === answerId);
    if (messageIndex > -1) {
      let record = messages.value.records[messageIndex];
      if (!record) {
        return
      }
      switch (reactionType) {
        case ReactionType.THUMBS_UP:
          record.thumbup = false;
          break;
        case ReactionType.THUMBS_DOWN:
        record.thumbdown = false;
          break;
      }
      messages.value.records[messageIndex] = record;
    }
  } catch (error) {
    console.error('Failed to update reaction:', error);
    let title = ""
    switch (reactionType) {
      case ReactionType.THUMBS_UP:
        title="取消点赞失败";
        break;
      case ReactionType.THUMBS_DOWN:
        title="取消狂踩失败";
        break;
    }
  }
};

// 添加编辑相关的状态
const showEditDialog = ref(false);
const editingMessage = ref({
  content: '',
  index: -1,
  originalMessage: null as P2MExchangeReocrdUnit | null
});

// 修改后的编辑处理函数
const handleEdit = (message: P2MExchangeReocrdUnit, index: number) => {
  editingMessage.value = {
    content: message.askRecord?.content || '',
    index: index,
    originalMessage: message
  };
  showEditDialog.value = true;
};

// 处理编辑确认
const handleEditConfirm = async (newContent: string) => {
  if (! messages.value) {
    return
  }
  const index = editingMessage.value.index;
  const originalMessage = editingMessage.value.originalMessage;
  
  if (index === -1 || !originalMessage || newContent === originalMessage.askRecord?.content) {
    return;
  }

  try {
    let askrecord = messages.value?.records[index].askRecord;
    if (askrecord == null) {
      return
    }
    askrecord.content = newContent;

    messages.value.records[index].askRecord = askrecord;

    // 清除选中状态，使操作框消失
    messages.value.records = messages.value.records.map(msg => ({
      ...msg,
      isSelected: false
    }));
    // 发送修改后的内容到后端
    if (wsSocket.value && wsSocket.value.status() === WebSocket.OPEN) {
      if (isPhaseEnd.value) {
        sendMessageViaWebSocket(newContent, Phase.HELLO);
        isPhaseEnd.value = false;
      } else {
        sendMessageViaWebSocket(newContent);
      }
    } else {
      const request = {
        content: newContent,
      } as CreateKnotRequest;
      
      console.log('Sending edited message to backend:');
      const response = await CreateKnot(request);
      console.log('Edit response:', response);
      
      // 更新当前会话ID
      currentKnotId.value = response.uid;
      // 建立新的WebSocket连接
      createWebSocketConnection(response.uid, response.urn);
    }
    
    // 显示成功提示
    // 这里可以使用你的提示组件或其他提示方式
    alert('修改成功');
    
  } catch (error) {
    console.error('Failed to send edited message:', error);
    // 如果发送失败，回滚修改
    if (! messages.value.records[index]) {
      return
    }
    messages.value.records[index].askRecord = originalMessage.askRecord;
    
    // 显示错误提示
    alert('修改失败，请重试');
  }
};

const handleTopicItemClick = async (item: TopicDef) => {
  console.log('plavv topic vue Item clicked:', item);
  topic.value = item
  let content = item.primary?.title || '';
  if (content !== '') {
    handleSend(content);
  }
};

// 处理编辑取消
const handleEditCancel = () => {
  if (! messages.value) {
    return;
  }
  // 清除选中状态
  messages.value.records = messages.value.records.map(msg => ({
    ...msg,
    isSelected: false
  }));
};

const handleMessageClick = (message: P2MExchangeReocrdUnit, index: number, event: any) => {
  if (! messages.value) {
    return;
  }
  console.error('handleMessageClick:', message, index, event);
  event.stopPropagation(); // 阻止事件冒泡
  messages.value.records = messages.value.records.map((msg, i) => ({
    ...msg,
    isSelected: i === index
  }));
};

const onScroll = (e: any) => {
  // 可以在这里添加自定滚动逻辑，如果需要的话
};    

// 修改复制功能实现
const handleCopy = (content: string|undefined) => {
  if (!content) return;
  navigator.clipboard.writeText(content).then(() => {
    ElMessage.success('复制成功');
  }).catch(() => {
    ElMessage.error('复制失败');
  });
};

const isMessageEnd = (message: P2MExchangeReocrdUnit) => {
  if (message.phase === Phase.End) {
    return true;
  }
  return false;
};

const sendMessageViaWebSocket = (message: string, p: Phase = Phase.Continue, id: string = "") => {
  const chatMessage = Exchange.create({
    phase: p,
    content: message, 
    askId: id,
    mode: RagMode[ragMode.value as keyof typeof RagMode] || RagMode.RAG_MODE_UNSPECIFIED,
  });

  if (knotFiles.value != null) {
    chatMessage.resources = knotFiles.value
  }

  const encodedMessage = Exchange.encode(chatMessage).finish();
  if (wsSocket.value && wsSocket.value.status() === WebSocket.OPEN) {
      wsSocket.value.send(encodedMessage);
  }
};

// 修改WebSocket连接实现
const createWebSocketConnection = (knotId: string, asKId: string) => {
  let u = getWssUrl();
  const wsUrl = `${u}/${knotId}`;
  console.log("open websocket:", wsUrl)
  wsSocket.value = new WebSocketClient(wsUrl, {onMessage:onSayMessage});
  wsSocket.value.connect(() => {
          console.log('Connection is ready!');
          sendMessageViaWebSocket("", Phase.HELLO, asKId)
  });
};

// 修改滚动实现
const scrollToBottom = () => {
  nextTick(() => {
    const container = document.querySelector('.chat-container');
    if (container) {
      setTimeout(() => {
        container.scrollTop = container.scrollHeight;
      }, 50);
    }
  });
};

const fetchTopics = async () => {
  console.log("fetch topic for subject:", subject.value)
  if (!subject.value) {
    return
  }
  
  const pageSize = 10

  const pageToken = { limit: pageSize, offset: 0 }
  ListTopics({
      subjectUrn: subject.value.urn,
      pageSize,
      pageToken,
      filter: ''
  }).then((res:ListTopicsResponse) => {
    topicsTotal.value = res.totalSize
    topics.value = res.topics
  })
}

const parseParamFromRoute = async () => {
  console.log("say parseParamFromRoute")
  try {
      const subjectUrn = route.query.subject
      let reloadSubject=true
      if (subjectUrn !==null && subjectUrn !== undefined && typeof subjectUrn === 'string') {
          if (subject.value != null) {
            if (subject.value.urn === subjectUrn) {
              reloadSubject = false
            }
          }
      }

      if (reloadSubject) {
        let req = {urn:subjectUrn} as GetSubjectRequest
        subject.value = await GetSubject(req)
      }

      if (subject.value != null) {
        isFavor.value = subject.value.isFavor || false
        selectedArtifact.value = subject.value.defaultResponder || ''
        console.log("granaryies:",subject.value.granaries)
        if (subject.value.granaries.length > 0) {
          console.log("set show upload")
          showUpload.value = true
        }

        console.log("selectedArtifact:", selectedArtifact.value)
      }
      

      const pageToken = { limit: 1000, offset: 0 }
      const filter = `role == 'AI_ASSISTANT'`
      let us = await ListUsers({ pageSize: 1000, pageToken, filter: filter })
      responders.value = us.users

      await fetchTopics()

  } catch (error) {
      console.error('Error parsing from route:', error)
  }
}

// 添加获取头像的计算函数
const getAvatarSrc = (message: P2MExchangeReocrdUnit) => {
  return message.answerRecord?.user?.avatar || qipuIcon;
};

const getThumbUpIcon = (message: P2MExchangeReocrdUnit) => {
  console.log("getThumbUpIcon:", message.thumbup)
  return message.thumbup ? thumbupActive : thumbup;
};

const getThumbDownIcon = (message: P2MExchangeReocrdUnit) => {
  console.log("getThumbDownIcon:", message.thumbdown)
  return message.thumbdown ? thumbdownActive : thumbdown;
};

const handleRegenerate = async (message: P2MExchangeReocrdUnit) => {
  if (!message.askRecord?.content) {
    console.warn('No content to regenerate');
    return;
  }
  
  if (!messages.value) {
    return;
  }

  handleStopAll()

  // Find the index of the current message
  const currentIndex = messages.value.records.findIndex(msg => msg === message);
  if (currentIndex === -1) {
    return;
  }

  // Remove all messages after the current one
  messages.value.records = messages.value.records.slice(0, currentIndex + 1);
  const messageIdsToDelete = messages.value.records
  .slice(currentIndex + 1)
  .map(msg => msg.answerId)
  .filter(id => id && id.trim().length > 0); 
  messageIdsToDelete.forEach(async (id) => {
    let req = {urn:id} as DeleteKnotRequest
    await DeleteKnot(req)
  })

  // Reset the current message's answer and phase
  message.answerRecord = {} as RecordUnit;
  message.phase = Phase.Begin;
  
  // Regenerate the response
  console.log("ask id:", message.askId)
  if (message.askId != null && message.askId != undefined && message.askId.length > 1) {
    handleSend(message.askRecord.content, true, message.askId);
  } else {
    handleSend(message.askRecord.content, true);
  }
};

// const virtualArtifacts = ref([
//   { urn: 'artifact1', name: '虚拟人1' },
//   { urn: 'artifact2', name: '虚拟人2' },
//   // ... 其他虚拟人 ...
// ]);

const virtualArtifacts = computed(() => responders.value.map(user => ({
  name: user.nickname || user.username,
  urn: user.urn
})))



const selectedArtifact =ref<string>('')
const currentArtifact = ref<string>('')


const handleSelectArtifact = (urn: string) => {
  console.log('选择的虚拟人:', urn);
  selectedArtifact.value = urn
  // 处理选择的虚拟人
};

const handleSelectRagMode = (mode: string) => {
  console.log('选择的召回模式:', mode);
  ragMode.value = mode
};

const loadKnotHistory = async () => {
  try {  
      console.log("loadKnots")
      if (userStore.userInfo == null || userStore.userInfo === undefined) {
          console.log("userinfo is null")
          return
      }
      
      const creatorFilter = `creator == "${userStore.userInfo.urn}" && subject == "${subject.value?.urn}" `
      // 增加pageSize以获取更多历史记录
      const response = await ListKnots({pageSize:50, filter:creatorFilter, pageToken:{limit:50, offset:0}}) 
      console.log(response)
      // 清空历史数组
      todayHistory.value = []
      weeklyHistory.value = []
      olderHistory.value = []

      response.Knots.forEach((knot: Knot) => {
          const knotDate = knot.createTime
          // 提取第一行作为标题
          let content = knot.content
          if (content) {
            // 提取第一行非空内容作为标题
            const lines = content.split('\n').filter(line => line.trim().length > 0)
            if (lines.length > 0) {
              content = lines[0].trim()
              // 限制标题长度
              if (content.length > 20) {
                content = content.substring(0, 20) + '...'
              }
            } else {
              content = '无标题对话'
            }
            // 更新显示内容
            knot.content = content
          }
          
          if (knotDate) {
            if (isToday(knotDate)) {
              todayHistory.value.push(knot)
            } else if (isThisWeek(knotDate)) {
              weeklyHistory.value.push(knot)
            } else {
              olderHistory.value.push(knot)
            }
          }
      })
      
      // 按时间降序排序
      todayHistory.value.sort((a, b) => 
        new Date(b.createTime || 0).getTime() - new Date(a.createTime || 0).getTime()
      )
      weeklyHistory.value.sort((a, b) => 
        new Date(b.createTime || 0).getTime() - new Date(a.createTime || 0).getTime()
      )
      olderHistory.value.sort((a, b) => 
        new Date(b.createTime || 0).getTime() - new Date(a.createTime || 0).getTime()
      )
  } catch (error) {
    console.error('gRPC request failed:', error);
  }
}
// 添加历史按钮点击处理函数
const handleHistoryClick = async () => {
  // 如果已经显示历史，则关闭它
  if (showHistory.value) {
    showHistory.value = false;
    return;
  }

  try {
    showHistory.value = true;
    loadingHistory.value = true;
    console.log('正在获取历史对话...');
    
    // 获取历史对话数据
    await loadKnotHistory();
    
    loadingHistory.value = false;
  } catch (error) {
    console.error('获取历史对话失败:', error);
    loadingHistory.value = false;
    ElMessage.error('获取历史对话失败');
  }
}

// 选择历史记录项
const selectHistoryItem = async (knot: Knot) => {
  console.log('选择历史对话:', knot);
  
  // 加载选定的历史对话
  if (knot && knot.urn) {
    try {
      // 清除当前对话
      if (messages.value) {
        messages.value.records = [];
      } else {
        // 创建一个新的消息记录对象
        const newRecord = {
          p2m: false,
          records: [],
          subject: knot.subject || '',
          subjectUrn: knot.subjectUrn || '',
          topic: knot.topicUrn || '',
          rootUrn: knot.urn,
          rootUid: knot.uid
        } as P2MExchangeRecord;
        messages.value = newRecord;
      }
      
      // 关闭现有WebSocket连接
      if (wsSocket.value) {
        wsSocket.value.close();
        wsSocket.value = null;
      }
      
      // 设置当前对话ID
     rootKnot.value = knot
      
      // 加载对话内容
      const request: ListKnotExchangesRequest = {
        urn: knot.urn
      };
      
      const response = await ListExchangeRecord(request);
      console.log('加载的对话内容:', response);
      
      // 设置对话记录
      if (response && response.records && response.records.length > 0) {
        messages.value = response.records[0];
      }
      
      // 重新建立WebSocket连接显示历史对话
      createWebSocketConnection(knot.uid, knot.urn);
      
      closeHistory();
      ElMessage.success('已加载历史对话');
    } catch (error) {
      console.error('加载历史对话失败:', error);
      ElMessage.error('加载历史对话失败');
    }
  }
};

// 添加历史相关状态
const showHistory = ref(false);
const loadingHistory = ref(false);

// 格式化时间


// 关闭历史侧边栏
const closeHistory = () => {
  showHistory.value = false;
};

onMounted(() => {
  // parseSubjectFromRoute()
  console.log("topic on mounted")
  if (!userStore.token) {
    ElMessage.warning('请先登录')
    router.push('/signin')
    return
  }

  if (userStore.subject != null) {
    subject.value = userStore.subject
  }

  if (userStore.topic != null) {
    topic.value = userStore.topic
  }

  parseParamFromRoute()
  
})

onUnmounted(() => {
  console.log("say onUnmounted")
  if (wsSocket.value) {
    console.log("say onUnmounted close wsSocket")
    wsSocket.value.close()
    wsSocket.value = null
  }
  isBlocking.value = false
  isPhaseEnd.value = true
  if (fetchTimeout.value) {
    clearTimeout(fetchTimeout.value)
  }
})

// 在script setup部分添加新的处理函数
const handleRelativeItemClick = (item: RelativeInfo) => {
  console.log('Relative item clicked:', item);
  // 这里可以添加处理relative项点击的逻辑
  // 例如：发送一个新的消息，显示相关话题的内容
  handleSend(item.title);
};

</script>

<style lang="scss" scoped>
/* 页面容器 - 水平排列各部分 */
.page-container {
  display: flex;
  height: 100vh;
  width: 100%;
  overflow: hidden;
}

/* 主内容区域 - 填充剩余空间 */
.main-content {
  flex: 1;
  margin-left: 200px;
  display: flex;
  flex-direction: column;
  transition: margin-left 0.3s ease;
  position: relative;
  height: 100vh;
  overflow: hidden;
}

/* 历史面板 - 默认宽度为0，当active时展开 */
.history-panel {
  width: 0;
  height: 100vh;
  background-color: #fff;
  border-right: 1px solid #EAECF0;
  overflow: hidden;
  transition: width 0.3s ease;
  position: fixed;
  right: 0;
  top: 0;
  z-index: 100;
  
  &.active {
    width: 280px;
    overflow-y: auto;
  }
}

.header-bar {
  display: flex;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid var(--border-color);
}

.topic-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.topic-title {
  font-size: 1rem;
  margin: 0;
}

/* 历史面板标题区域 */
.history-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #EAECF0;
  white-space: nowrap;
  
  h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
  }
  
  .close-btn {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: #8E8E93;
    
    &:hover {
      color: #1C1C1E;
    }
  }
}

/* 历史内容区域 */
.history-content {
  padding: 0;
  min-width: 280px;
}

/* 历史项目 */
.history-item {
  padding: 12px 16px;
  cursor: pointer;
  border-bottom: 1px solid #F2F2F7;
  white-space: nowrap;
  
  &:hover {
    background-color: #F7F7F8;
  }
  
  .history-item-title {
    font-size: 14px;
    margin-bottom: 4px;
    color: #1C1C1E;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  
  .history-item-time {
    font-size: 12px;
    color: #8E8E93;
  }
}

.loading-history, .empty-history {
  padding: 16px;
  text-align: center;
  color: #8E8E93;
  font-size: 14px;
  white-space: nowrap;
}

/* 聊天容器 */
.chat-container {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 20px 0;
}

/* 消息容器 */
.message-wrapper {
  display: flex;
  flex-direction: column;
  width: 100%;
  margin-bottom: 16px;
}

.topic-list {
  width: 100%;
  max-width: 700px;
  margin: 0 auto;
}

.topic-item {
  padding: 12px 16px;
  margin-bottom: 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
  text-align: left;
  background-color: #fff;
  font-size: 14px;
  
  &:hover {
    background-color: var(--hover-bg-color);
  }
}

/* 基础消息样式 */
.message {
  margin-bottom: 24px;
}

/* 用户消息 - 靠右 */
.message.user {
  
  display: flex;
  justify-content: flex-end;
  .message-content {
    max-width: 600px;
    .text {
      background-color: #4E89FD;
      color: #ffffff;
      border-radius: 12px;
      padding: 12px 16px;
      font-size: 14px;
      line-height: 1.6;
    }
  }
}

/* 系统消息 - 靠左 */
.message.system {
  align-self: flex-start;
  display: flex;
  
  .message-header {
    margin-right: 12px;
    
    .avatar {
      width: 28px;
      height: 28px;
      border-radius: 8px;
    }
  }

  .message-content {
    flex: 1;
    width: 600px;
    text-align: left;
    
    .text {
      background-color: #F7F7F8;
      border-radius: 12px;
      padding: 12px 16px;
      padding-bottom: 20px;
      font-size: 14px;
      line-height: 1.6;
      color: #1C1C1E;
      position: relative;
    }
  }
}

/* 去掉居中配置，使消息能靠左/靠右对齐 */
.messages-wrapper {
  display: flex;
  flex-direction: column;
  max-width: 800px;
  margin: 0 auto;
  padding: 0 16px;
  width: 100%;
}

/* 输入区域 */
.input-container {
  padding: 16px;
  border-top: 1px solid #EAECF0;
  background-color: #fff;
}

.input-wrapper {
  max-width: 800px;
  margin: 0 auto;
  padding: 0 16px;
}

.message-actions {
  position: absolute;
  bottom: 1px;
  right: 4px;
  display: flex;
  gap: 4px;
  
  button {
    background: none;
    border: none;
    padding: 3px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    
    img {
      width: 16px;
      height: 16px;
    }

    &:hover {
      opacity: 0.8;
    }

    &.active {
      img {
        filter: brightness(0.8) sepia(1) saturate(5) hue-rotate(180deg);
      }
    }
  }
}

.stop-output-btn {
  position: absolute;
  bottom: 8px;
  right: 8px;
  
  button {
    background: none;
    border: none;
    padding: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    
    img {
      width: 20px;
      height: 20px;
    }

    &:hover {
      opacity: 0.8;
    }
  }
}

/* 添加历史分组样式 */
.history-section {
  margin-bottom: 16px;
}

.history-section-title {
  padding: 8px 16px;
  font-size: 12px;
  font-weight: 500;
  color: #8E8E93;
  background-color: #F7F7F8;
}

.empty-section {
  padding: 12px 16px;
  color: #8E8E93;
  font-size: 12px;
  text-align: center;
  font-style: italic;
}

/* 添加relative信息列表样式 */
.relatives-list {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #EAECF0;
}

.relatives-title {
  font-size: 14px;
  color: #8E8E93;
  margin-bottom: 8px;
  font-weight: 500;
}

.relative-item {
  display: block;
  padding: 8px 12px;
  margin: 4px 0;
  background-color: #F7F7F8;
  border-radius: 8px;
  font-size: 13px;
  color: #4E89FD;
  cursor: pointer;
  transition: all 0.2s ease;
  width: 100%;
  text-align: left;
  
  &:hover {
    background-color: #E5E5EA;
    color: #3A6BC7;
  }
}

/* 主题显示区域样式 */
.topic-display {
  text-align: center;
  margin-bottom: 24px;
  padding: 16px;
  background-color: #F7F7F8;
  border-radius: 12px;
  
  h2 {
    margin: 0 0 8px 0;
    font-size: 20px;
    font-weight: 600;
    color: #1C1C1E;
  }
  
  p {
    margin: 0;
    font-size: 14px;
    color: #8E8E93;
    line-height: 1.5;
  }
}

</style>